Add AutoEP + AutoTP parallel folding#8064
Conversation
Allow tensor parallelism (AutoTP) for the dense/attention path to coexist with expert parallelism (AutoEP) for routed experts on the same rank set, without requiring EP to be a subset of DP. - Treat dense and MoE as independent partitionings: dense view tp*dp, expert view ep*etp*edp, with dp/edp derived so tp*dp == ep*etp*edp == stage_size. expert_tensor_parallel_size is reserved (must currently be 1). - Express folding via the existing tensor_parallel/expert_parallel config sections, with divisibility, TP/sequence-parallel exclusivity, and preset_model consistency validation. - Add the route-full / partition-dispatch MoE path and AutoTP skipping of AutoEP subtrees; derive folded process groups via the generalized expert/data-parallel group creation. - Reduce TP-replicated router/gate gradients mode-aware (sum when tokens are partitioned, average when replicated); record per-parameter-family ZeRO checkpoint metadata and handle folded ZeRO-1/2 optimizer state. - Add folding unit tests (config, groups, dispatch, runtime, gradient parity, checkpoint), including multi-rank GPU-gated cases. Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 278c919489
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Comment-only; no behavior change. Make the folded TP/SP gradient SUM-vs-AVERAGE policy and its reasoning explicit in the code: - mark_autoep_folding_* contracts: router_gate_replicated is the only marker applied on the live forward path (AVERAGE); routed-token-partial and SP-sharded-LayerNorm are future-only SUM contracts pinned by unit tests. - _AllGatherVariableRows / restore_combined: document the tp_size factor the restore all-gather backward injects, which makes the folded router/gate arrive replicated (AVERAGE) and why SUM reproduces the 2.0x parity regression the CPU/Gloo tests guard. - partition_assignments: the drop-before-all-to-all keeps EP dispatch at 1x volume, and the reconstruction is what makes the gradient replicated. - Strategy classifier: the router-vs-LayerNorm asymmetry (router can be a tp/sp partial because it rides the dispatch all-to-all; LayerNorm only under true SP) and the underlying gathered=AVERAGE / sharded=SUM rule. Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Lift the temporary fail-fast that forced expert parallelism to be a subset of data parallelism (expert_width = ep*etp <= dp and dp % expert_width == 0) and support cross-lane EP, where an EP group may span TP lanes and dense-DP ranks (e.g. world=4 TP4/EP4/dp1, or world=4 TP2/DP2/EP4). The folded group tables already lay EP groups across the tp-lane-major rank ordering, so only the validation gate and the routed-expert gradient reduction needed to change. Fix routed-expert gradient over-scaling under folding. The folded forward all-gathers expert outputs into a replicated full view in restore_combined, whose backward injects a tp_size factor (the same factor the replicated router cancels via AVERAGE). Routed experts were classified SKIP, so that factor survived and the expert weight gradient reached the optimizer tp_size times too large. This was invisible to scale-invariant Adam but real for non-adaptive optimizers and for gradient clipping (it inflates the expert contribution to the global grad norm), and it grows with tp_size in cross-lane shapes. Routed experts now use a dedicated EXPERT_TP_CANCEL reduction that divides the gradient by tp_size with no TP all_reduce; the division is linear and composes with the existing expert-data-parallel all_reduce in any order. The per-family gradient convention is otherwise unchanged and is now justified for the general cross-lane layout: each family's reduction is keyed to its replication structure, not the EP layout. Router/gate and dense/LayerNorm AVERAGE over the TP (token-replication) group; routed experts cancel the restore tp_size factor and reduce data-parallel over the EDP group. Add CPU/Gloo parity coverage for cross-lane shapes (router/gate and LayerNorm vs a non-folded baseline at world=4 TP2/EP4 and TP4/EP4/dp1) and SGD-based expert-weight parity (post-step weight equality vs the non-folded baseline) for the MVP shape and cross-lane shapes including edp>1. Adam is scale-invariant, so the expert test uses SGD to actually exercise the gradient magnitude. Update the folding config/group-table tests: cross-lane shapes are now accepted, and the cross-lane EP/EDP rank tables are asserted. Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
|
@tohtana Thanks for the extensive amount of work, super appreciated. A couple of questions (I will also run some tests on my end):
|
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
PKUWZP
left a comment
There was a problem hiding this comment.
Thanks for this comprehensive PR @tohtana. What I understand about this PR is that it enables AutoTP (tensor parallelism for the dense/attention path) and AutoEP (expert parallelism for routed experts) coexist on the same ranks without forcing EP to be a subset of DP. It adds a folding topology module (auto_ep_folding.py), a route-full/partition-dispatch MoE path (ep_tp_dispatch.py), per-parameter-family gradient reduction (AVERAGE for replicated router/dense, a tp_size-cancel for routed experts), and per-family ZeRO checkpoint metadata. the parity tests are fp32 + non-partitioned only, which leaves a class of gradient-pipeline configs unexercised.
One risk from my perspective is that the folded TP gradient reduction is bolted onto allreduce_gradients() reading param.grad, but several permitted configs consume, snapshot, or clear param.grad before that point — so the correction silently doesn't apply.
Several thoughts on this PR:
deepspeed/runtime/engine.py:2825— BF16 folded gradients skip the TP reduction entirely. In_backward_epilogue,self.optimizer.backward_epilogue()(→update_hp_grads, which doeshp_grad.data.add_(lp.grad...)) runs beforeallreduce_gradients(), which is where_reduce_autoep_folding_tp_replicated_gradients()mutateslp.gradin place. The optimizer steps on the fp32 HP buffer built from the uncorrected LP grad. With bf16 + tp_size>1 (permitted —validate_folding_globaldoesn't reject it, and the parity tests are fp32-only), routed-expert grads staytp_sizemultiply, which is too large and router/dense grads are never averaged → wrong global grad norm/clipping (and wrong updates under SGD/Lion/Muon).deepspeed/runtime/zero/stage_1_and_2.py:1033— ZeRO-1 +overlap_commloses the folding reduction._maybe_reduce_autoep_folding_tp_gradientearly-returns onnot self.partition_gradients, delegating stage-1 to the engine boundary sweep. Butoverlap_comm=Trueinstalls reduce hooks (line 625) that clearparam.grad = Noneduring backward (lines 1045/1066), so by the time_reduce_autoep_folding_tp_replicated_gradientsruns it finds grad is None and skips every param. The potential effect: no TP folding correction for ZeRO-1 +overlap_comm, with no fail-fast guard flag.deepspeed/runtime/engine.py:2745— DeepCompile silently bypasses the foldingreduction. allreduce_gradients()returns early whenis_deepcompile_active()andnot self.compile_autosp(), before reaching_reduce_autoep_folding_tp_replicated_gradients()(line 2751). Nothing invalidate_folding_globalrejects DeepCompile + folding, so a folded DeepCompile run produces uncorrected gradients with no error.
1-3 are the ones we should act on before merge — ideally by adding an explicit fail-fast in validate_folding_global for bf16/overlap_comm/DeepCompile until the reduction is integrated into the real gradient pipeline (or moving the correction to where the fp32/partitioned grads are actually assembled).
I think the PR is almost ready to be merged. Let me know your thoughts:) Great work! @tohtana
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
Signed-off-by: Masahiro Tanaka <mtanaka@anyscale.com>
|
Hi @PKUWZP,
|
This PR adds parallel folding for AutoEP: tensor parallelism (AutoTP) for the dense/attention path can now coexist with expert parallelism (AutoEP) for the routed-expert path on the same set of ranks, without forcing EP to be a subset of DP — an EP group may span TP lanes and dense-DP ranks (cross-lane EP).
(This PR should be adjusted for ZeRO3 support after #8060 is merged)
Design
Attention/dense and MoE are treated as two independent partitionings of the same rank set, parameterized per parameter family:
stage_size = tp * dpstage_size = ep * etp * edpdpandedpare always derived, never user-configured, so the invarianttp * dp == ep * etp * edp == stage_sizecannot be broken from config. The only structural requirement is that the expert width tiles the stage (stage_size % (ep * etp) == 0); EP groups are then laid across a TP-lane-major rank ordering, so they may span TP lanes and dense-DP ranks.Configuration
No new config section. Folding is expressed by the coexistence of the existing
tensor_parallelandexpert_parallelsections:{ "tensor_parallel": { "autotp_size": 4 }, "expert_parallel": { "enabled": true, "autoep_size": 4, "expert_tensor_parallel_size": 1 } }expert_tensor_parallel_sizeis carried as a config field but currently must be1(expert-internal TP is reserved as follow-up and rejected fail-fast). Validation enforces stage divisibility, TP/sequence-parallel exclusivity, andpreset_modelconsistency between the two sections.Cross-lane expert parallelism
Expert parallelism no longer has to be a subset of data parallelism. Shapes where the expert width exceeds (or does not divide) the dense data-parallel size are supported, for example:
world=4, TP=4, EP=4(dp=1): the EP group is the whole TP group — one expert per rank.world=4, TP=2, EP=4(dp=2): the EP group spans both TP lanes and both DP ranks.world=8, TP=4, EP=4(dp=2, edp=2): EP groups span TP lanes with expert replication.The per-family gradient convention is keyed to each parameter's replication structure, not to the EP layout, so it holds across the whole
tp*dppool:restore_combined, whose all-gather backward injects atp_sizefactor that AVERAGE divides out.restore_combinedtp_sizefactor (divide bytp_size, no TP all-reduce) and reduce data-parallel over the expert-data-parallel (EDP) group. Without the cancellation, folded expert gradients are over-scaled bytp_size— invisible to scale-invariant Adam, but real for non-adaptive optimizers and for gradient clipping (it inflates the expert contribution to the global grad norm). This is now fixed for all folded shapes (the MVP TP2×EP4 shape included).What's included
mp_modeTP-strided vs SP-consecutive ordering), including cross-lane EP group tables.deepspeed/moe/ep_tp_dispatch.py), with AutoTP skipping AutoEP subtrees.tp_sizecancellation for routed experts; SKIP for genuinely TP-sharded params; SUM contracts reserved for a future true sequence-parallel path.Correctness & validation
ep>dp) and TP4×EP4 (4-rank,dp=1); scale 1.0.edp=1andedp=2.edp=1andedp=2); cross-lane folded training runs with finite loss and finite, non-zero expert/router gradients.aws-torch-latest-full) on H100 GPUs.Scope / follow-ups
etp=1. The replicated-grad reduction is mode-aware so the sequence-parallel (Ulysses) folding case fits the same contract; AutoTP + AutoEP is the validated path here.expert_tensor_parallel_size > 1) is reserved for a follow-up.